home *** CD-ROM | disk | FTP | other *** search
-
- /*------------------------------------------------------------------------*
- * Title : c.man
- * Purpose : Manual page find utility
- * allows searching via index, page filename, volume, wildcards
- * and by content.
- * History : 10:57 20-Dec-90 Created.
- * 19:40 completed.
- * 23:40 Added -k option.
- * 10:30 21-Dec-90 Fixed bug with search_index
- * It didn't read every Name entry, skipped some.
- *------------------------------------------------------------------------*/
-
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include <signal.h>
- #include <kernel.h>
-
- #define CHK(p) ((p)?p:"NULL")
- #define FALSE 0
- #define TRUE (!FALSE)
-
- extern int wildmat(char *,char *);
- extern int search_index(char *);
- extern void search_page(char *);
- extern void vol_scan(const char *,char *);
- extern void escape(int );
- extern void syntax(const char *);
- extern char *read_sys_var(const char *);
-
- char *version="1.01";
- char *root_dir=NULL;
- char *keyword=NULL, *search=NULL, *volume=NULL, *page=NULL, *com=NULL;
- int index=0,found=0,nk=0;
-
- #if defined(MY_WILDCARD_ROUTINE)
- /* ------------------------ wildmat ------------------------------------
- * Purpose : given a wildcarded string and a string, determines
- * whether a match exists between the two.
- * Paramaters : pointer to wildcarded string
- * pointer to string
- * Returns : 0 if no match,
- * 1 if matched.
- */
-
- int wildmat(char *s,char *wcs)
- {
- int i,j=0;
- for (i=0; i<strlen(s); i++) /* going through string serially */
- {
- if ( (wcs[j]=='\0') && (s[i+1]!='\0') ) return 0;
- if (wcs[j]=='*') /* A * can replace 0 or more chars */
- {
- while (wcs[j]=='*') j++; /* gets rid of double *'s */
- while (s[i])
- { /* First find the occurance of the character after the wildcard
- * in the string. Note: & 0xDF to convert lowercase to uppercase.
- */
- if ((s[i] & 0xDF) != (wcs[j] & 0xDF) ) i++;
- else
- if ( (s[i+1] & 0xDF) == (s[i] & 0xDF) )
- { /* find last character in sequence of same chars */
- i++;
- continue;
- }
- else break;
- }
- }
- if ((wcs[j] & 0xDF) == (s[i] & 0xDF)) j++; else return 0;
- }
- if (j<strlen(wcs)) { /* wildcard string not finished with */
- for (;j<strlen(wcs);j++) {
- if (wcs[j]!='*') return 0; /* must be all *'s to match */
- }
- return 1;
- }
- else return 1;
- }
- #else
-
- /*
- ** Do shell-style pattern matching for ?, \, [], and * characters.
- ** Might not be robust in face of malformed patterns; e.g., "foo[a-"
- ** could cause a segmentation violation. I think it's 8bit clean.
- **
- ** Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986.
- ** rsalz@bbn.com (Rich Salz)
- */
- /* Mods for ANSI compiler by S.van Aardt (Mon 14, Jan 1991) */
-
- extern int wildmat(register char *,register char *);
-
- static int Star(register char *text, register char *p)
- {
- while (!wildmat(text, p)) if (*++text == '\0') return FALSE;
- return TRUE;
- }
-
-
- int wildmat(register char *text,register char *p)
- {
- register int last;
- register int matched;
- register int reverse;
-
- for ( ; *p; text++, p++)
- switch (*p) {
- case '\\':
- /* Literal match with following character. */
- p++;
- /* FALLTHROUGH */
- default:
- if (tolower(*text) != tolower(*p)) /* SvA - "case-less" */
- return FALSE;
- continue;
- case '?':
- /* Match anything. */
- if (*text == '\0')
- return FALSE;
- continue;
- case '*':
- /* Trailing star matches everything. */
- return *++p ? Star(text, p) : TRUE;
- case '[':
- /* [^....] means inverse character class. */
- if (reverse = p[1] == '^')
- p++;
- for (last = 0400, matched = FALSE; *++p && *p != ']'; last = *p)
- /* This next line requires a good C compiler. */
- if (*p == '-' ? *text <= *++p && *text >= last : *text == *p)
- matched = TRUE;
- if (matched == reverse)
- return FALSE;
- continue;
- }
-
- return *text == '\0';
- }
-
- #endif
-
-
- /*-------------- search_index ----------------------------------------
- * Purpoe : searches an index page for matches with a (wildcarded)
- * string.
- * Parameters : pointer to pathname of index page.
- * Returns : void
- */
-
- int search_index(char *pathname)
- {
- FILE *fp=fopen(pathname,"r");
- int matches=0;
- if (!fp) {
- fprintf(stderr,"Error: Couldn't open index page \"%s\"\n",pathname);
- exit(1);
- }
- else {
- while (!feof(fp)) {
- char fname[40]={0},pname[80]={0},sink[132]={0};
- fscanf(fp," %s %s",fname ,pname );
- fgets(sink,132,fp);
- if ( (wildmat("Name",fname)) && (wildmat("Appears",pname)) ) break;
- }
- while (!feof(fp)) {
- char fname[40]={0},pname[40]={0},sink[132]={0};
- fscanf(fp," %s %s",fname ,pname );
- fgets(sink,132,fp);
- if ( (fname[0]!=' ') && (wildmat(fname,keyword)) ) {
- char *pg=NULL,*vol=NULL;
- int i=0,j=0;
- for (i=0; ((pname[i]) && (pname[i]!='(')); i++);
- pg=calloc(sizeof(char),i+1);
- strncpy(pg,pname,i);
- for (j=++i; ((pname[i]) && (pname[i]!=')')); i++);
- vol=calloc(sizeof(char),i-j+1);
- strncpy(vol,(pname+j),i-j);
- if (pg) {
- const int pl=strlen(root_dir)+3+strlen(vol);
- char *pathname;
- pathname=calloc(sizeof(char),pl);
- strcpy(pathname,root_dir); /* current path */
- strcat(pathname,"."); /* + directory name */
- strcat(pathname,vol);
- nk=1;
- matches++;
- vol_scan(pathname,pg); /* recursive call into directory */
- nk=0;
- free(pathname);
- }
- free(vol);
- free(pg);
- }
- }
- fclose(fp);
- }
- return matches;
- }
-
-
- /*-------------- search_page -----------------------------------
- * Purpoe : searches a page for matches with a (wildcarded)
- * string.
- * Parameters : pointer to pathname of page
- * Returns : void
- */
-
- void search_page(char *pathname)
- {
- FILE *fp=fopen(pathname,"r");
- long int i=0;
- if (fp)
- {
- while (!feof(fp)) {
- char *buffer=NULL;
- int n=0,c=0;
- i=ftell(fp);
- for (n=0;((!feof(fp))&&((fgetc(fp))!='\n'));n++);
- if (n) {
- fseek(fp,(long) i,SEEK_SET);
- buffer=calloc(sizeof(char),n+2);
- for (n=0; ((!feof(fp))&&((c=fgetc(fp))!='\n')); n++) {
- if (!feof(fp)) buffer[n]=c; else buffer[n]='\0';
- }
- }
- if (buffer) {
- int m=0;
- char *p,*s="()[]'`~`@#$%^&*_-+={}\\|:;\"<>,.?/ ";
- char *bfr;
- bfr=calloc(sizeof(char),strlen(buffer)+1);
- strcpy(bfr,buffer);
- p=strtok(bfr,s);
- if (wildmat(p,search)) m=1;
- while (p=strtok(NULL,s)) if (wildmat(p,search)) m=1;
- if (m) fprintf(stderr,"%s : %s\n",pathname,buffer);
- free(bfr);
- }
- free(buffer);
- }
- fclose(fp);
- }
- else {
- fprintf(stderr,"Error: Couldn't open page \"%s\"\n",pathname);
- exit(1);
- }
- }
-
-
- /* -------------------------- vol_scan ---------------------------------
- * Purpose : tree-walks a directory sub-tree looking for matches
- * with the wildcard name (global).
- * Parameters : pathname of directory to scan
- * Returns : void
- */
-
-
- void vol_scan(const char *path,char *page)
- {
- _kernel_swi_regs regs_in={0}, regs_out={0}; /* registers pre & post call */
- _kernel_oserror *errnum;
- int s=29+strlen(path)+11; /* lengths of the file record + pathname string */
- char *buffer;
- buffer=calloc(sizeof(char),s); /* allocate a buffer of suitable size */
- regs_in.r[0]=11; /* Read file information from a specified directory */
- regs_in.r[1]=(int) path; /* specified directory */
- regs_in.r[2]=(int) buffer; /* destination data buffer */
- regs_in.r[3]=1; /* number of objects to read */
- regs_in.r[4]=0; /* offset of first item to be read */
- regs_in.r[5]=s; /* length of buffer */
- regs_in.r[6]=0; /* General wildcard '*' to get all */
- do
- {
- errnum=_kernel_swi(0x0C, ®s_in, ®s_out); /* SWI "OS_GBPB" */
- if (!errnum) /* ie if no errors */
- {
- if (regs_out.r[3]==1) /* ie if something read */
- {
- if (((int) *(buffer+16))==2) /* object is a directory */
- { /* make a string containg the full pathname now */
- const int pl=strlen(path)+3+strlen((buffer+29));
- char *pathname;
- pathname=calloc(sizeof(char),pl);
- strcpy(pathname,path); /* current path */
- strcat(pathname,"."); /* + directory name */
- strcat(pathname,(buffer+29));
- vol_scan(pathname,page); /* recursive call into directory */
- free(pathname);
- }
- else
- {
- char *name;
- name=(buffer+29);
- if ((nk) || (!keyword))
- {
- if (wildmat(name,page)) /* page filename matches search page ? */
- {
- found=1;
- if (!index)
- {
- /* create full pathname & if required tag to display command */
- const int pl=strlen(com)+strlen(path)+4+strlen((buffer+29));
- char *pathname;
- int err;
- pathname=calloc(sizeof(char),pl);
- if (!search)
- {
- strcpy(pathname,com);
- strcat(pathname," ");
- strcat(pathname,path);
- }
- else strcpy(pathname,path);
- strcat(pathname,"."); /* + directory name */
- strcat(pathname,(buffer+29));
-
- if (!search)
- {
- err=_kernel_system(pathname,0);
- if (err)
- {
- fprintf(stderr,"\n\n");
- exit(1);
- }
- }
- else search_page(pathname);
- }
- else
- {
- fprintf(stdout,"Volume %s ",(path+strlen(root_dir)+1));
- fprintf(stdout,"Page %s\n",(buffer+29) );
- }
- }
- }
- else
- {
- if ((wildmat(name,"list"))) /* filename matches list page ? */
- {
- const int pl=strlen(path)+3+strlen((buffer+29));
- char *pathname;
- int matches=0;
- pathname=calloc(sizeof(char),pl);
- strcpy(pathname,path); /* current path */
- strcat(pathname,"."); /* + directory name */
- strcat(pathname,(buffer+29));
- matches=search_index(pathname);
- free(pathname);
- }
- }
- }
- regs_in.r[4]=regs_out.r[4]; /* offset of next item to read */
- }
- }
- else {
- if (!nk) fprintf(stderr,"Error : Manual path \"%s\" not found\n",path);
- break;
- }
- }
- while ((regs_out.r[4]!=-1)&&(regs_out.r[3]==1));
- free(buffer);
- }
-
- /*-------------------- escape ---------------------------------------
- * Purpose : handles signal interrupts, exits from the program
- * Parameters : signal code
- * Returns : void
- */
- void escape(int sig)
- {
- if (sig!=4) {
- fprintf(stderr,"Aborted by Interrupt %d\n",sig);
- } else fprintf(stderr,"\n");
- exit(1);
- }
-
- /*-------------------- syntax --------------------------*
- * Purpose : Displays syntax message about program
- * Parameters : pointer to program name (argv[0])
- * Returns : void
- *------------------------------------------------------*/
- void syntax_message(const char *prog_name)
- {
- char *syntax="[section] [title] [-k keyword] [-s string] [-i]";
- fprintf(stderr,"usage: %s %s\n",prog_name,syntax);
- fprintf(stderr,"author: S. van Aardt\n");
- fprintf(stderr,"version: %s (%s)\n", version, __DATE__);
- fprintf(stderr," section Search within manual section #\n");
- fprintf(stderr," title Page to search for\n");
- fprintf(stderr," -k Search page lists for keyword\n");
- fprintf(stderr," -i Display pages available\n");
- fprintf(stderr," -s Search through pages for word\n");
- fprintf(stderr,"Note: wildcards are available in searches\n");
- exit(1);
- }
-
-
- /*-------------------- read_sys_var ---------------------------*
- * Purpose : Obtain the value of a system variable.
- * Arguments : pointer to name of system variable to be read.
- * Returns : pointer to value read.
- *-------------------------------------------------------------*/
-
- char *read_sys_var(const char *variable)
- {
- _kernel_swi_regs pre={0}, post={0}; /* registers pre & post call */
- _kernel_oserror *errnum;
- char *buffer=calloc(sizeof(char),255);
- pre.r[0]=(int) variable;
- pre.r[1]=(int) buffer;
- pre.r[2]=255;
- pre.r[3]=0;
- pre.r[4]=3;
- errnum=_kernel_swi(0x23, &pre, &post); /* SWI "OS_ReadVarVal" */
- if (!errnum) {
- return buffer;
- } else {
- free(buffer);
- return NULL;
- }
- }
-
-
- int main(int argc,char *argv[])
- {
- int c=0,okay=1,rf=1;
- extern char *optarg;
- extern int optind;
- extern int getopt(int argc,char **argv, char *optstring);
-
- signal(SIGINT, escape); /* When interrupted by Escape call 'escape' */
-
- root_dir=read_sys_var("man$path"); /* where to find manual pages */
- if (!root_dir) {
- root_dir="$.usr.man"; /* use this if no man$path */
- rf=0; /* & note that I can't free root_dir now */
- }
- com=read_sys_var("man$com"); /* describes command for displaying pages */
- if (!com) com="TYPE ";
- /* Parse command line arguments */
- while ((c = getopt(argc,argv,"ik:s:?")) != -1) {
- switch (c) {
- case 'k' : /* keyword search through indexes */
- keyword=optarg;
- break;
- case 's' : /* word search through each page */
- search=optarg;
- break;
- case 'i' : /* produce index of page names */
- index=1;
- break;
- case '?' : /* produce syntax message */
- okay=0;
- break;
- }
- }
- if (okay) {
- if (optind<argc) { /* if more arguments are left to parse */
- int i=optind;
- for (i=optind; i<argc; i++) {
- char *p=argv[i],c=p[0];
- if isdigit(c) { /* then assume referring to manual volume */
- if (!volume) volume=p;
- else {
- fprintf(stderr,"invalid arguments\n");
- syntax_message(argv[0]);
- break;
- }
- }
- else {
- if (!page) page=p;
- else {
- fprintf(stderr,"Argument error\n");
- syntax_message(argv[0]);
- break;
- }
- }
- }
- }
- if ((!volume) && (!page) && (!keyword) && (!search) && (!index))
- syntax_message(argv[0]);
- if ((!page) && (!keyword) && (!search) && (!index)) {
- fprintf(stderr,"Error no page given\n");
- syntax_message(argv[0]);
- }
- if (!page) page="*";
- if (volume) {
- const int pl=strlen(root_dir)+3+strlen(volume);
- char *pathname;
- pathname=calloc(sizeof(char),pl);
- strcpy(pathname,root_dir); /* current path */
- strcat(pathname,"."); /* + directory name */
- strcat(pathname,volume);
- vol_scan(pathname,page); /* search through a specific manual volume */
- free(pathname);
- }
- else vol_scan(root_dir,page); /* go through all manual volumes */
- if (!found) fprintf(stderr,"Manual page %s not found\n",page);
- } else syntax_message(argv[0]);
- if ((root_dir)&&(rf)) free(root_dir);
- if (com) free(com);
- return 0;
- }
-
-